package com.aliwo.controller;

import com.alibaba.fastjson.JSONObject;
import com.aliwo.constant.IllegalSqlUtil;
import com.aliwo.enums.DataSourceEnum;
import com.aliwo.exception.ControllerException;
import com.aliwo.request.SaveSqlJobInfoRequest;
import com.aliwo.service.SqlService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import tech.powerjob.common.response.ResultDTO;

import java.util.Optional;

/**
 * @author:xuyayuan
 * @date:2021/7/26 13:33
 * @description:TODO
 */
@SuppressWarnings("all")
@Api(tags = "sql处理器模块")
@RestController
@RequestMapping("/powerjob/sql")
public class SqlController {
    private static final Logger logger = LoggerFactory.getLogger(SqlController.class);
    @Autowired
    private SqlService sqlService;

    @ApiOperation("sql新增任务")
    @PostMapping("/save")
    public ResponseEntity<Long> saveSqlJobInfo(@ApiParam(value = "httpAIP创建任务请求对象")
                                               @RequestBody SaveSqlJobInfoRequest request) throws Exception {
        this.preValid(request);
        ResultDTO<Long> sqlResultDTO = sqlService.saveSqlJob(request);
        return ResponseEntity.ok(sqlResultDTO.getData());
    }

    // 开启一键校验sql合规接口
    @ApiOperation("校验sql合规")
    @PostMapping("/checkSql")
    public ResponseEntity<Void> checkSql(@ApiParam(value = "校验sql语句") @RequestBody String execSql) throws Exception {
        if (StringUtils.isBlank(execSql)) {
            new ControllerException("APP:SCHEDULE:SQL_JOB_SAVE", "执行语句不能为空", "ControllerException.schedule.info.execSql_notEmpty");
        }
        Optional.ofNullable(execSql)
                .orElseThrow(() -> new ControllerException("APP:SCHEDULE:SQL_JOB_SAVE", "执行语句不能为空",
                        "ControllerException.schedule.info.execSql_notEmpty"));
        String errMsg = IllegalSqlUtil.getAllIllegalSqlInfo(execSql);
        if (errMsg != null) {
            new ControllerException("APP:SCHEDULE:SQL_JOB_SAVE", "sql语句存在非法字符 {} ", errMsg);
        }
        return ResponseEntity.noContent().build();
    }

    /**
     * 功能描述:字段校验
     * @author xuyayuan
     * @param saveSqlJobInfoRequest
     * @param params
     * @return void
     */
    private void preValid(SaveSqlJobInfoRequest saveSqlJobInfoRequest) {
        saveSqlJobInfoRequest.valid();
        Optional.ofNullable(saveSqlJobInfoRequest.getHost())
                .orElseThrow(() -> new ControllerException("APP:SCHEDULE:SQL_JOB_SAVE", "主机地址不能为空",
                        "ControllerException.schedule.info.host_notEmpty"));

        Optional.ofNullable(saveSqlJobInfoRequest.getUserName())
                .orElseThrow(() -> new ControllerException("APP:SCHEDULE:SQL_JOB_SAVE", "用户名不能为空",
                        "ControllerException.schedule.info.username_notEmpty"));

        Optional.ofNullable(saveSqlJobInfoRequest.getPassword())
                .orElseThrow(() -> new ControllerException("APP:SCHEDULE:SQL_JOB_SAVE", "密码不能为空",
                        "ControllerException.schedule.info.password_notEmpty"));

        Optional.ofNullable(saveSqlJobInfoRequest.getDatabaseName())
                .orElseThrow(() -> new ControllerException("APP:SCHEDULE:SQL_JOB_SAVE", "数据库不能为空",
                        "ControllerException.schedule.info.databaseName_notEmpty"));

        Optional.ofNullable(saveSqlJobInfoRequest.getExecSql())
                .orElseThrow(() -> new ControllerException("APP:SCHEDULE:SQL_JOB_SAVE", "执行语句不能为空",
                        "ControllerException.schedule.info.execSql_notEmpty"));

        Optional.ofNullable(IllegalSqlUtil.getIllegalSqlInfo(saveSqlJobInfoRequest.getExecSql())).ifPresent(execSql -> {
            new ControllerException("APP:SCHEDULE:SQL_JOB_SAVE", "sql语句存在非法字符 {} ",
                    IllegalSqlUtil.getIllegalSqlInfo(saveSqlJobInfoRequest.getExecSql()));
        });
        JSONObject params = new JSONObject();
        params.put("sql", saveSqlJobInfoRequest.getExecSql());
        params.put("user", saveSqlJobInfoRequest.getUserName());
        params.put("password", saveSqlJobInfoRequest.getPassword());
        params.put("dataSourceName", saveSqlJobInfoRequest.getDataSourceName());
        Optional.ofNullable(saveSqlJobInfoRequest.getTimeout()).ifPresent(timeOut -> {
            params.put("timeout", saveSqlJobInfoRequest.getTimeout());
        });
        Optional.ofNullable(saveSqlJobInfoRequest.getShowResult()).ifPresent(showResult -> {
            params.put("showResult", saveSqlJobInfoRequest.getShowResult());
        });
        StringBuilder jdbcUrl = new StringBuilder();
        this.adapterJdbcUrl(saveSqlJobInfoRequest, params, jdbcUrl);
        params.put("jdbcUrl", jdbcUrl);
        saveSqlJobInfoRequest.setProcessorInfo("tech.powerjob.official.processors.impl.sql" +
                ".DynamicDatasourceSqlProcessor");
        saveSqlJobInfoRequest.setJobParams(params.toJSONString());
    }

    /**
     * 功能描述:适配不同的url连接
     *
     * @param saveSqlJobInfoRequest
     * @param params
     * @param jdbcUrl
     * @return void
     * @author xuyayuan
     */
    private void adapterJdbcUrl(SaveSqlJobInfoRequest saveSqlJobInfoRequest, JSONObject params, StringBuilder jdbcUrl) {
        // mysql适配
        if (StringUtils.isBlank(saveSqlJobInfoRequest.getDataSourceName()) ||
                DataSourceEnum.MYSQL_TYPE.getDataSourceType().equalsIgnoreCase(saveSqlJobInfoRequest.getDataSourceName())) {
            jdbcUrl = jdbcUrl
                    .append("jdbc:mysql://")
                    .append(saveSqlJobInfoRequest.getHost())
                    .append(":")
                    .append("3306")
                    .append("/")
                    .append(saveSqlJobInfoRequest.getDatabaseName())
                    .append("?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
            return;
        }
        // TODO oracle 适配
        if (DataSourceEnum.ORACLE_TYPE.getDataSourceType().equalsIgnoreCase(saveSqlJobInfoRequest.getDataSourceName())) {
            //jdbcUrl = jdbcUrl
            //        .append("jdbc:mysql://")
            //        .append(saveSqlJobInfoRequest.getHost())
            //        .append(":")
            //        .append("3306")
            //        .append("/")
            //        .append(saveSqlJobInfoRequest.getDatabaseName())
            //        .append("?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
            return;
        }
        // TODO openplant 适配
        if (DataSourceEnum.OPENPLANT_TYPE.getDataSourceType().equalsIgnoreCase(saveSqlJobInfoRequest.getDataSourceName())) {
            //jdbcUrl = jdbcUrl
            //        .append("jdbc:mysql://")
            //        .append(saveSqlJobInfoRequest.getHost())
            //        .append(":")
            //        .append("3306")
            //        .append("/")
            //        .append(saveSqlJobInfoRequest.getDatabaseName())
            //        .append("?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
            return;
        }

        // TODO postgresql 适配
        if (DataSourceEnum.POSTGRESQL_TYPE.getDataSourceType().equalsIgnoreCase(saveSqlJobInfoRequest.getDataSourceName())) {
            //jdbcUrl = jdbcUrl
            //        .append("jdbc:mysql://")
            //        .append(saveSqlJobInfoRequest.getHost())
            //        .append(":")
            //        .append("3306")
            //        .append("/")
            //        .append(saveSqlJobInfoRequest.getDatabaseName())
            //        .append("?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
            return;
        }
    }
}
